#include "parameters.h"
#include "cache.h"

int get_parameter(vstring **line)
{
    if(!is_null(line))
    {
        if(remove_occour(line,ACCEPT))
            return V_ACCEPT;

        if(remove_occour(line,ACCEPT_CHARSET))
            return V_ACCEPT_CHARSET;

        if(remove_occour(line,ACCEPT_ENCODING))
            return V_ACCEPT_ENCODING;

        if(remove_occour(line,ACCEPT_LANGUAGE))
            return V_ACCEPT_LANGUAGE;

        if(remove_occour(line,ACCEPT_RANGES))
            return V_ACCEPT_RANGES;

        if(remove_occour(line,AGE))
            return V_AGE;

        if(remove_occour(line,ALLOW))
            return V_ALLOW;

        if(remove_occour(line,AUTHORIZATION))
            return V_AUTHORIZATION;

        if(remove_occour(line,CACHE_CONTROL))
            return V_CACHE_CONTROL;

        if(remove_occour(line,CONNECTION))
            return V_CONNECTION;

        if(remove_occour(line,CONTENT_ENCODING))
            return V_CONTENT_ENCODING;

        if(remove_occour(line,CONTENT_LANGUAGE))
            return V_CONTENT_LANGUAGE;

        if(remove_occour(line,CONTENT_LENGTH))
            return V_CONTENT_LENGTH;

        if(remove_occour(line,CONTENT_LOCATION))
            return V_CONTENT_LOCATION;

        if(remove_occour(line,CONTENT_MD5))
            return V_CONTENT_MD5;

        if(remove_occour(line,CONTENT_RANGE))
            return V_CONTENT_RANGE;

        if(remove_occour(line,CONTENT_TYPE))
            return V_CONTENT_TYPE;

        if(remove_occour(line,DATE))
            return V_DATE;

        if(remove_occour(line,ETAG))
            return V_ETAG;

        if(remove_occour(line,EXPECT))
            return V_EXPECT;

        if(remove_occour(line,EXPIRES))
            return V_EXPIRES;

        if(remove_occour(line,FROM))
            return V_FROM;

        if(remove_occour(line,HOST))
            return V_HOST;

        if(remove_occour(line,IF_MATCH))
            return V_IF_MATCH;

        if(remove_occour(line,IF_MODIFIED_SINCE))
            return V_IF_MODIFIED_SINCE;

        if(remove_occour(line,IF_NONE_MATCH))
            return V_IF_NONE_MATCH;

        if(remove_occour(line,IF_RANGE))
            return V_IF_RANGE;

        if(remove_occour(line,IF_UNMODIFIED_SINCE))
            return V_IF_UNMODIFIED_SINCE;

        if(remove_occour(line,LAST_MODIFIED))
            return V_LAST_MODIFIED;

        if(remove_occour(line,LOCATION))
            return V_LOCATION;

        if(remove_occour(line,MAX_FORWARDS))
            return V_MAX_FORWARDS;

        if(remove_occour(line,PRAGMA))
            return V_PRAGMA;

        if(remove_occour(line,PROXY_AUTHENTICATE))
            return V_PROXY_AUTHENTICATE;

        if(remove_occour(line,PROXY_AUTHORIZATION))
            return V_PROXY_AUTHORIZATION;

        if(remove_occour(line,RANGE))
            return V_RANGE;

        if(remove_occour(line,REFERER))
            return V_REFERER;

        if(remove_occour(line,RETRY_AFTER))
            return V_RETRY_AFTER;

        if(remove_occour(line,SERVER))
            return V_SERVER;

        if(remove_occour(line,TE))
            return V_TE;

        if(remove_occour(line,TRAILER))
            return V_TRAILER;

        if(remove_occour(line,TRANSFER_ENCODING))
            return V_TRANSFER_ENCODING;

        if(remove_occour(line,UPGRADE))
            return V_UPGRADE;

        if(remove_occour(line,USER_AGENT))
            return V_USER_AGENT;

        if(remove_occour(line,VARY))
            return V_VARY;

        if(remove_occour(line,VIA))
            return V_VIA;

        if(remove_occour(line,WARNING))
            return V_WARNING;

        if(remove_occour(line,WWW_AUTHENTICATE))
            return V_WWW_AUTHENTICATE;
        return V_UNKNOW;
    }
    return V_END;
}

int get_method(vstring **value)
{
    if(strcmp((*value)->pt,STR_GET) == 0)
        return GET;

    if(strcmp((*value)->pt,STR_HEAD) == 0)
        return HEAD;

    if(strcmp((*value)->pt,STR_POST) == 0)
        return POST;

    if(strcmp((*value)->pt,STR_PUT) == 0)
        return PUT;

    if(strcmp((*value)->pt,STR_DELETE) == 0)
        return DELETE;

    if(strcmp((*value)->pt,STR_TRACE) == 0)
        return TRACE;

    if(strcmp((*value)->pt,STR_CONNECT) == 0)
        return CONNECT;
    return 0;
}
/**
 * PARÂMETRO 6 - AGE
 * PARÂMETRO 13 - CONTENT-LENGTH
 */
int get_number(vstring **line)
{
    int num;
    trim(line);
    string_to_integer(*line,&num);
    return num;
}
/**
 * PARÂMETRO 7 - ALLOW
 */
void get_allow(vstring **line,int allow[8])
{
    vstring *value = NULL;

    replace_all(line,DASH,SPACE);

    while(*line != NULL)
    {
        trim(line);
        get_token(line,&value,COMMA);
        trim(&value);
        allow[get_method(&value)] = 1; // indica que o método retornado é suportado
    }
}
/**
 * PARÂMETRO 9 - CACHE-CONTROL
 */
cache_control* get_cache_control(vstring **line,int is_response)
{
    vstring *value = NULL,*aux = NULL;
    cache_control *cc = new_cache_control();

    while(*line != NULL)
    {
        trim(line);
        get_token(line,&value,COMMA);

        if(strstr(value->pt,"no-store") != NULL)
            cc->no_store = 1;
        if(strstr(value->pt,"no-transform") != NULL)
            cc->no_transform = 1;
        if(strstr(value->pt,"only-if-cached") != NULL)
            cc->only_if_cached = 1;
        if(strstr(value->pt,"must-revalidate") != NULL)
            cc->must_revalidate = 1;
        if(strstr(value->pt,"proxy-revalidate") != NULL)
            cc->proxy_revalidate = 1;
        if(strstr(value->pt,"public") != NULL)
            cc->is_public = 1;
        else
            if(strstr(value->pt,"private") != NULL)
            {
                cc->is_public = 0;
                if(replace_occour(&value,EQUAL,SPACE))
                {
                    get_token(&value,&aux,SPACE);
                    trim(&value);
                    copy_vstring(&(cc->field_name),value);
                }
            }

        if(strstr(value->pt,"no-cache") != NULL)
        {
            cc->no_cache = 1;
            if(is_response) // se for de resposta tem um field name depois do '='
            {
                if(replace_occour(&value,EQUAL,SPACE))
                {
                    get_token(&value,&aux,SPACE);
                    trim(&value);
                    copy_vstring(&(cc->field_name),value);
                }
            }
        }

        if(strstr(value->pt,"max-age") != NULL)
        {
            if(replace_occour(&value,EQUAL,SPACE))
            {
                get_token(&value,&aux,SPACE);
                trim(&value);
                string_to_integer(value,&(cc->max_age));
            }
        }

        if(strstr(value->pt,"max-stale") != NULL)
        {
            if(replace_occour(&value,EQUAL,SPACE))
            {
                get_token(&value,&aux,SPACE);
                trim(&value);
                string_to_integer(value,&(cc->max_stale));
            }
        }

        if(strstr(value->pt,"min-fresh") != NULL)
        {
            if(replace_occour(&value,EQUAL,SPACE))
            {
                get_token(&value,&aux,SPACE);
                trim(&value);
                string_to_integer(value,&(cc->min_fresh));
            }
        }
        free_string(&aux);
    }
    // TODO tratar control extensions

    return cc;
}
/**
 * PARÂMETRO 10 - CONNECTION
 */
int get_connection(vstring **line)
{
    if(remove_occour(line,"close"))
        return 0;
    return 1;
}
/**
 * PARÂMETRO 18 - DATE
 */
struct tm* get_date(vstring **line)
{
    int num;
    vstring *aux = NULL,*value = NULL;
    struct tm *date = (struct tm *) malloc(sizeof(struct tm));
    date->tm_mday = 0; // servirá de indicador para descobrir se um número é dia ou ano (pg 15 RFC 2616)

    replace_all(line,DASH,SPACE);

    while(*line != NULL)
    {
        trim(line);
        get_token(line,&value,SPACE);

        if(convert_month(value) >= 0)
            date->tm_mon = convert_month(value);
        else
            if(strstr(value->pt,":") != NULL)
            {
                copy_substring(&aux,value,0,2); // copiando hora
                string_to_integer(aux,&(date->tm_hour));
                copy_substring(&aux,value,3,2); // copiando minuto
                string_to_integer(aux,&(date->tm_min));
                copy_substring(&aux,value,6,2); // copiando segundo
                string_to_integer(aux,&(date->tm_sec));
            }
            else
                if(string_to_integer(value,&num))
                {
                    if(!date->tm_mday)
                        date->tm_mday = num;
                    else
                        if(num > 1900)
                            date->tm_year = num - 1900;
                        else
                            date->tm_year = num;
                }
    }
    mktime(date); // preenche o restante da estrutura que estiver faltando

    return date;
}
/**
 * PARÂMETRO 23 - HOST
 */
void get_host(vstring **line,header_data **hd)
{
    trim(line);
    get_token(line,&((*hd)->host),COLON);
    get_token(line,&((*hd)->port),COLON);
}

void get_referer(vstring **line,header_data **hd)
{
    int index;

    remove_all(line,CR);
    remove_all(line,END_LINE);
    copy_vstring(&((*hd)->srv_request),(*hd)->request);
    free_string(&((*hd)->srv_url));

    if((index = get_index_occour(line,"http://")) >= 0)
        remove_occour(line,"http://");
    remove_occour(line,SLASH);
    concat_vstring(&((*hd)->srv_url),*line);
}

int get_transfer_encoding(vstring **line)
{
    if(remove_occour(line,"chunked"))
        return 1;
    return 0;
}